package com.muyu.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.muyu.common.core.utils.ObjUtils;
import com.muyu.product.domain.*;
import com.muyu.product.domain.base.CategoryBase;
import com.muyu.product.domain.model.CategoryInfoSaveModel;
import com.muyu.product.domain.model.TemplateAttributeGroupModel;
import com.muyu.product.domain.model.TemplateAttributeModel;
import com.muyu.product.domain.resp.CategoryCommonElementResp;
import com.muyu.product.domain.resp.CategoryParentCommonElementResp;
import com.muyu.product.mapper.CategoryInfoMapper;
import com.muyu.product.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Stream;

/**
 * 品类信息Service业务层处理
 *
 * @author DongZeLiang
 * @date 2024-02-27
 */
@Slf4j
@Service
public class CategoryInfoServiceImpl extends ServiceImpl<CategoryInfoMapper, CategoryInfo> implements CategoryInfoService {


    @Autowired
    private AsCategoryAttributeService asCategoryAttributeService;

    @Autowired
    private AsCategoryAttributeGroupService asCategoryAttributeGroupService;

    @Autowired
    private AsCategoryBrandService asCategoryBrandService;

    @Autowired
    private AsAttributeGroupService asAttributeGroupService;

    @Autowired
    private AttributeInfoService attributeInfoService;

    @Autowired
    private BrandInfoService brandInfoService;

    @Autowired
    private AttributeGroupService attributeGroupService;

    /**
     * 查询品类信息列表
     *
     * @param categoryInfo 品类信息
     *
     * @return 品类信息
     */
    @Override
    public List<CategoryInfo> list (CategoryInfo categoryInfo) {
        LambdaQueryWrapper<CategoryInfo> queryWrapper = new LambdaQueryWrapper<>();


        if (ObjUtils.notNull(categoryInfo.getName())) {
            queryWrapper.like(CategoryInfo::getName, categoryInfo.getName());
        }

        if (ObjUtils.notNull(categoryInfo.getImage())) {
            queryWrapper.eq(CategoryInfo::getImage, categoryInfo.getImage());
        }

        if (ObjUtils.notNull(categoryInfo.getParentId())) {
            queryWrapper.eq(CategoryInfo::getParentId, categoryInfo.getParentId());
        }

        if (ObjUtils.notNull(categoryInfo.getStart())) {
            queryWrapper.eq(CategoryInfo::getStart, categoryInfo.getStart());
        }

        if (ObjUtils.notNull(categoryInfo.getIntroduction())) {
            queryWrapper.eq(CategoryInfo::getIntroduction, categoryInfo.getIntroduction());
        }

        return list(queryWrapper);
    }

    @Override
    @Transactional
    public boolean save (CategoryInfoSaveModel categoryInfoSaveModel) {
        CategoryInfo categoryInfo = CategoryInfo.saveModelBuild(categoryInfoSaveModel);
        boolean save = this.save(categoryInfo);
        Long categoryInfoId = categoryInfo.getId();
        List<Long> attributeIdList = categoryInfoSaveModel.getAttributeIdList();
        if (attributeIdList != null && !attributeIdList.isEmpty()) {
            asCategoryAttributeService.saveBatch(
                    attributeIdList.stream()
                            .map(attributeId -> AsCategoryAttribute.categoryBuild(categoryInfoId, attributeId))
                            .toList()
            );
        }
        List<Long> attributeGroupIdList = categoryInfoSaveModel.getAttributeGroupIdList();
        if (attributeGroupIdList != null && !attributeGroupIdList.isEmpty()) {
            asCategoryAttributeGroupService.saveBatch(
                    attributeGroupIdList.stream()
                            .map(attributeGroupId -> AsCategoryAttributeGroup.categoryBuild(categoryInfoId, attributeGroupId))
                            .toList()
            );
        }
        List<Long> brandIdList = categoryInfoSaveModel.getBrandIdList();
        if (brandIdList != null && !brandIdList.isEmpty()) {
            asCategoryBrandService.saveBatch(
                    brandIdList.stream()
                            .map(brandId -> AsCategoryBrand.categoryBuild(categoryInfoId, brandId))
                            .toList()
            );
        }
        return save;
    }

    /**
     * 通过品类ID获取父级以上的属性组集合
     *
     * @param categoryId 品类ID
     *
     * @return 父级以上的属性组集合
     */
    @Override
    public List<AttributeGroup> getAttributeGroup (Long categoryId) {
        List<AttributeGroup> attributeGroupList = new ArrayList<>();
        LambdaQueryWrapper<AsCategoryAttributeGroup> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AsCategoryAttributeGroup::getCategoryId, categoryId);
        List<AsCategoryAttributeGroup> asCategoryAttributeGroupList = asCategoryAttributeGroupService.list(queryWrapper);
        if (asCategoryAttributeGroupList != null && !asCategoryAttributeGroupList.isEmpty()) {
            List<Long> attributeGroupIdList = asCategoryAttributeGroupList.stream()
                    .map(AsCategoryAttributeGroup::getAttributeGroupId)
                    .toList();
            attributeGroupList.addAll(attributeGroupService.listByIds(attributeGroupIdList));
        }
        CategoryInfo categoryInfo = this.getById(categoryId);
        if (categoryInfo.getParentId() != 0) {
            if (attributeGroupList.isEmpty()) {
                attributeGroupList.addAll(getAttributeGroup(categoryInfo.getParentId()));
            } else {
                List<AttributeGroup> attributeGroups = getAttributeGroup(categoryInfo.getParentId());
                attributeGroups.forEach(attributeGroup -> {
                    if (!attributeGroupList.contains(attributeGroup)) {
                        attributeGroupList.add(attributeGroup);
                    }
                });
            }
        }
        return attributeGroupList;
    }

    /**
     * 通过品类ID获取父级以上的品牌集合
     *
     * @param categoryId 品类ID
     *
     * @return 父级以上的品牌集合
     */
    @Override
    public List<BrandInfo> getBrand (Long categoryId) {
        List<BrandInfo> brandInfoList = new ArrayList<>();
        LambdaQueryWrapper<AsCategoryBrand> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AsCategoryBrand::getCategoryId, categoryId);
        List<AsCategoryBrand> asCategoryBrandList = asCategoryBrandService.list(queryWrapper);
        if (asCategoryBrandList != null && !asCategoryBrandList.isEmpty()) {
            List<Long> brandIdList = asCategoryBrandList.stream()
                    .map(AsCategoryBrand::getBrandId)
                    .toList();
            brandInfoList.addAll(brandInfoService.listByIds(brandIdList));
        }
        CategoryInfo categoryInfo = this.getById(categoryId);
        if (categoryInfo.getParentId() != 0) {
            if (brandInfoList.isEmpty()) {
                brandInfoList.addAll(getBrand(categoryInfo.getParentId()));
            } else {
                List<BrandInfo> brandInfos = getBrand(categoryInfo.getParentId());
                brandInfos.forEach(brandInfo -> {
                    if (!brandInfoList.contains(brandInfo)) {
                        brandInfoList.add(brandInfo);
                    }
                });
            }

        }
        return brandInfoList;
    }

    /**
     * 通过品类ID获取父级以上的属性集合
     *
     * @param categoryId 品类ID
     *
     * @return 父级以上的属性集合
     */
    @Override
    public List<AttributeInfo> getAttribute (Long categoryId) {
        List<AttributeInfo> attributeInfoList = new ArrayList<>();
        LambdaQueryWrapper<AsCategoryAttribute> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AsCategoryAttribute::getCategoryId, categoryId);
        List<AsCategoryAttribute> asCategoryAttributeList = asCategoryAttributeService.list(queryWrapper);
        if (asCategoryAttributeList != null && !asCategoryAttributeList.isEmpty()) {
            List<Long> attributeIdList = asCategoryAttributeList.stream()
                    .map(AsCategoryAttribute::getAttributeId)
                    .toList();
            attributeInfoList.addAll(attributeInfoService.listByIds(attributeIdList));
        }
        CategoryInfo categoryInfo = this.getById(categoryId);
        if (categoryInfo.getParentId() != 0) {
            if (attributeInfoList.isEmpty()) {
                attributeInfoList.addAll(getAttribute(categoryInfo.getParentId()));
            } else {
                List<AttributeInfo> attributeInfos = getAttribute(categoryInfo.getParentId());
                attributeInfos.forEach(attributeInfoQuery -> {
                    if (!attributeInfoList.contains(attributeInfoQuery)) {
                        attributeInfoList.add(attributeInfoQuery);
                    }
                });
            }
        }
        return attributeInfoList;
    }


    public <T, AS> List<T> getCommon (Long categoryId, IService<AS> iService, IService<T> bsiService) {
        List<T> list = new ArrayList();
        QueryWrapper<AS> asQueryWrapper = new QueryWrapper<>();
        asQueryWrapper.eq("category_id", categoryId);
        List<AS> asList = iService.list(asQueryWrapper);
        if (asList != null && !asList.isEmpty()) {
            List<Long> baseIdList = asList.stream()
                    .map(as -> {
                        if (as instanceof CategoryBase categoryBase) {
                            return categoryBase.getBaseId();
                        }
                        return null;
                    })
                    .toList();
            list.addAll(bsiService.listByIds(baseIdList));
        }
        CategoryInfo categoryInfo = this.getById(categoryId);
        if (categoryInfo.getParentId() != 0) {
            if (list.isEmpty()) {
                list.addAll(getCommon(categoryInfo.getParentId(), iService, bsiService));
            } else {
                List<T> commonList = getCommon(categoryInfo.getParentId(), iService, bsiService);
                commonList.forEach(common -> {
                    if (!list.contains(common)) {
                        list.add(common);
                    }
                });
            }
        }
        return list;
    }

    /**
     * 通过品类ID获取父级以上的属性、属性组、品牌集合
     *
     * @param categoryId 品类ID
     *
     * @return 父级以上的属性、属性组、品牌集合
     */
    @Override
    public CategoryParentCommonElementResp parentCommonElement (Long categoryId) {
        return CategoryParentCommonElementResp.builder()
                .attributeInfoList(getCommon(categoryId, asCategoryAttributeService, attributeInfoService))
                .attributeGroupList(getCommon(categoryId, asCategoryAttributeGroupService, attributeGroupService))
                .brandInfoList(getCommon(categoryId, asCategoryBrandService, brandInfoService))
                .build();
    }

    private void getParentIdListByCateGoryId(List<Long> parentIdList, Long cateGoryId){
        if (cateGoryId.equals(0L)){
            return;
        }
        CategoryInfo categoryInfo = this.getById(cateGoryId);
        parentIdList.add(categoryInfo.getId());
        getParentIdListByCateGoryId(parentIdList, categoryInfo.getParentId());
    }

    /**
     * 通过品类ID获取品类共有属性
     *
     * @param cateGoryId 品类ID
     *
     * @return 品类共有属性
     */
    @Override
    public CategoryCommonElementResp getTemplateAttributeByCateGoryId (Long cateGoryId) {
        List<Long> cateGoryIdList = new ArrayList<>();
        getParentIdListByCateGoryId(cateGoryIdList, cateGoryId);
        // 取出和品类相关联的属性组关系  - 中间表
        LambdaQueryWrapper<AsCategoryAttributeGroup> asCategoryAttributeGroupLambdaQueryWrapper = new LambdaQueryWrapper<>(){{
            in(AsCategoryAttributeGroup::getCategoryId, cateGoryIdList);
        }};
        List<AsCategoryAttributeGroup> categoryAttributeGroupList = asCategoryAttributeGroupService.list(asCategoryAttributeGroupLambdaQueryWrapper);
        List<TemplateAttributeGroupModel>  attributeGroupModelList = categoryAttributeGroupList.stream()
                .map(AsCategoryAttributeGroup::getAttributeGroupId)
                .distinct()
                .map(attributeGroupId -> TemplateAttributeGroupModel.attributeGroupBuild(
                        attributeGroupService.getById(attributeGroupId),
                        applyAttributeGroupId -> {
                            LambdaQueryWrapper<AsAttributeGroup> asAttributeGroupQueryWrapper = new LambdaQueryWrapper<>() {{
                                eq(AsAttributeGroup::getGroupId, applyAttributeGroupId);
                            }};
                            List<Long> attributeIdList = asAttributeGroupService.list(asAttributeGroupQueryWrapper).stream()
                                    .map(AsAttributeGroup::getAttributeId)
                                    .toList();
                            if (attributeIdList.isEmpty()) {
                                return new ArrayList<>();
                            }
                            return attributeInfoService.listByIds(attributeIdList).stream()
                                    .map(AttributeInfo::buildTemplateModel)
                                    .toList();
                        }
                ))
                .filter(TemplateAttributeGroupModel::isEffective)
                .toList();
        // 查重集合
        Set<Long> attributeIdSet = new HashSet<>();
        // 获取组内所有的属性Id
        if (!attributeGroupModelList.isEmpty()){
            attributeIdSet.addAll(
                    attributeGroupModelList.stream()
                            .flatMap((Function<TemplateAttributeGroupModel, Stream<TemplateAttributeModel>>) templateAttributeGroupModel -> templateAttributeGroupModel.getAttributeList().stream())
                            .map(TemplateAttributeModel::getId)
                            .toList()
            );
        }

        List<TemplateAttributeModel> templateAttributeModelList = new ArrayList<>();
        LambdaQueryWrapper<AsCategoryAttribute> categoryAttributeQueryWrapper = new LambdaQueryWrapper<>();
        categoryAttributeQueryWrapper.in(AsCategoryAttribute::getCategoryId, cateGoryIdList);
        List<AsCategoryAttribute> asCategoryAttributeList = asCategoryAttributeService.list(categoryAttributeQueryWrapper);
        if (asCategoryAttributeList != null && !asCategoryAttributeList.isEmpty()){
            List<Long> templateAttributeIdList = asCategoryAttributeList.stream()
                    .map(AsCategoryAttribute::getAttributeId)
                    .filter(templateAttributeId -> !attributeIdSet.contains(templateAttributeId))
                    .toList();
            templateAttributeModelList = attributeInfoService.listByIds(templateAttributeIdList).stream()
                    .map(AttributeInfo::buildTemplateModel)
                    .toList();
        }

        List<TemplateAttributeModel> attributeModelList = new ArrayList<>();

        if (!templateAttributeModelList.isEmpty()){
            attributeIdSet.addAll(
                    templateAttributeModelList.stream().map(TemplateAttributeModel::getId).toList()
            );
        }

        LambdaQueryWrapper<AttributeInfo> attributeInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        attributeInfoLambdaQueryWrapper.notIn(!attributeIdSet.isEmpty(), AttributeInfo::getId, attributeIdSet);
        attributeModelList = attributeInfoService.list(attributeInfoLambdaQueryWrapper).stream().map(AttributeInfo::buildTemplateModel).toList();

        return CategoryCommonElementResp.builder()
                .templateAttributeGroupList(attributeGroupModelList)
                .templateAttributeList(templateAttributeModelList)
                .attributeList(attributeModelList)
                .build();
    }
}
